home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1999 July / Macworld (1999-07).dmg / Shareware World / Info / For Developers / Mops 3.4.sea / Mops source / Toolbox classes / TextEdit < prev    next >
Text File  |  1998-07-15  |  10KB  |  441 lines

  1. \ Oct95 JRF Added noClip to Activate: & Deactivate: per MRH suggestion
  2.     \ modified New: to enable outline highliting of inactive TE
  3.  
  4. \ 25May93 DBH  Added lastchar: to commonize a routine.
  5.     \ added kludge to #lines: to fix a bug.
  6.     \ Completely reworked currentline: to fix a speed problem.
  7.  
  8. \ 15May93 DBH  Added textaddr: method to improve readability and code reuse.
  9.     \ Use textaddr: self in getline: .
  10.     \ Deleted addrlinestart: method because it is never reused.
  11.     \ Added lineEnd: method, so we can move there easily.
  12.     \ Delte general class declaration.
  13. \ 11May93 DBH  fixed getLine: so null is returned if last char in TE is
  14.     \ a carriage return.  Added getpoint: and idle: methods.
  15.  
  16. \ 3Sep96 mrh  added values lineStart and lineEnd, set by a getLine: call
  17. \ Jan 98 mrh  fixed TE scrap stuff for PowerPC
  18.  
  19.  
  20. PPC? [IF]  syscall TESetScrapLength  [THEN]        \ not a call on 68k
  21.  
  22. need terecord
  23.  
  24. variable OFFSET  \ used in GetScrap call
  25.  
  26. 0    value    LINESTART    \ these are set when we call getLine: - useful sometimes
  27. 0    value    LINEEND
  28.  
  29.  
  30. \ some routines to handle the clipboard
  31.  
  32. : TODESK        ( -- oserr )
  33.     ZeroScrap ?EXIT                    \ out if error
  34. [ ppc? ] [if]
  35.     TEGetScrapLength                \ length
  36. [else]
  37.     global TEScrpLength w@
  38. [then]
  39.     'type TEXT                      \ theType
  40.     TEScrapHandle  @
  41.     PutScrap
  42. ;
  43.  
  44.  
  45.  : FROMDESK     ( -- oserr )
  46.     TEScrapHandle
  47.     'type TEXT      \ theType
  48.     offset
  49.     GetScrap
  50. [ ppc? ] [if]
  51.     dup 0>= IF  TESetScrapLength
  52.                 0                            \ no error
  53.             THEN
  54. [else]
  55.     dup 0>=    IF  global TEScrpLength w!        \ store scrap length
  56.                 0                            \ no error
  57.             THEN
  58. [then]
  59.  
  60.  
  61.  
  62. : SELCUT
  63.         actW IF cut: [ actW ] THEN ;
  64.  
  65. : SELCOPY
  66.         actW IF copy: [ actW ] THEN ;
  67.  
  68. : SELPASTE
  69.     actW IF  paste: [ actW ]  THEN ;
  70.  
  71. : SELCLEAR
  72.     actW IF  clear: [ actW ]  THEN ;
  73.  
  74.  
  75. :class  RGBColor  super{ object }
  76. 68k_record
  77. {    uint    red
  78.     uint    green
  79.     uint    blue
  80. }
  81.  
  82. :m SETCOLOR:    \ ( red green blue -- )
  83.     put: blue  put: green  put: red  ;m
  84.  
  85. :m GETCOLOR:    \ ( -- red green blue )
  86.     get: red  get: green  get: blue  ;m
  87.  
  88. ;class
  89.  
  90. \ Note an object of class RGBColor will start off black, unless we change it.
  91.  
  92.  
  93. :class TextStyle  super{ object }
  94.  
  95. public
  96. 68k_record
  97. {    int            tsFont
  98.     byte        tsFace
  99.     int            tsSize
  100.     RGBColor    tsColor
  101. }
  102.  
  103. :m classinit:    9 put: tsSize  ;m
  104.  
  105. ;class
  106.  
  107. TextStyle    theStyle
  108.  
  109. \ syscall TENew
  110. \ syscall TEStyleNew
  111. \ syscall TextFont
  112. \ syscall TextSize
  113. \ syscall    TESetStyle
  114.  
  115. handle    textHandle
  116.  
  117.  
  118. :CLASS TextEdit super{ object }
  119.  
  120.     handle    TEHandle
  121. public
  122.     bool    styles?
  123. end_public
  124.  
  125. :m useStyles:    set: styles?  ;m        \ get rid of it when I fix the bug!
  126.  
  127. :m new:    { dest view -- }
  128.  
  129.     9 TextSize                \ need a smallish initial default value
  130.     dest
  131.     view
  132.     get: styles?
  133.     IF        TEStyleNew
  134.     ELSE    TENew
  135.     THEN  put: TEHandle
  136.  
  137.     2 1                    \ 2 selects OutlineHilite feature
  138.     get: TEHandle        \ 1 sets its flag
  139.     TEFeatureFlag
  140.     drop                \ don't want the returned result
  141. ;m
  142.  
  143. :m handle:    ( -- tehandle )
  144.     get: TEHandle ;m
  145.  
  146. :m ptr:    ( -- teRecord )
  147.     ptr: TEHandle ;m
  148.  
  149.  
  150. :m noWrap:
  151.     ptr: self  noWrap: teRecord  ;m
  152.  
  153. :m WrapIt:
  154.     ptr: self  wrapIt: teRecord  ;m
  155.  
  156.  
  157. :m >font:  ( font# -- )
  158.     put: ivar> tsFont in theStyle
  159.     1 ( font )  theStyle  false  get: TEHandle  TESetStyle
  160. ;m
  161.  
  162. :m >fontSize:  ( n -- )
  163.     put: ivar> tsSize in theStyle
  164.     4 ( size )  theStyle  false  get: TEHandle  TESetStyle
  165. ;m
  166.  
  167. :m >color:  ( red green blue -- )
  168.     setColor: ivar> tsColor in theStyle
  169.     8 ( color )  theStyle  false  get: TEHandle  TESetStyle
  170. ;m
  171.  
  172. :m >style:  ( n -- )
  173.     put: ivar> tsFace in theStyle
  174.     2 ( face )  theStyle  false  get: TEHandle  TESetStyle
  175. ;m
  176.  
  177. :m SETVIEWRECT:  { left top rt bot \ adr -- }
  178.     ptr: TEHandle  -> adr    \ ptr: TEHandle setview: teRecord ;m  ??    \ 19May93 DBH
  179.     top  adr  8 +  w!  left  adr 10 + w!
  180.     bot  adr 12 +  w!    rt  adr 14 + w!  ;m
  181.  
  182.  
  183. :m LINEHEIGHT:  ( -- n )
  184.     ptr: TEHandle lineHeight: teRecord ;m
  185.  
  186. \ :m #lines:    ( -- n)
  187. \    ptr: TEHandle  #lines: teRecord    \ note message to class
  188. \    ;m
  189.  
  190. :m cut:
  191.     get: TEHandle  TECut
  192.     todesk  drop ;m            \ not looking at error
  193.  
  194. :m copy:
  195.     get: TEHandle  TECopy
  196.     todesk drop ;m            \ not looking at error
  197.  
  198. :m paste:
  199.     fromdesk  ?EXIT            \ out if error
  200.     get: TEHandle  TEPaste ;m
  201.  
  202. :m clear:
  203.     0 0  SetOrigin
  204.     get: TEHandle  TEDelete  ;m
  205.  
  206.  
  207. :m update:    \ ( rptr -- )
  208.     0 0  SetOrigin
  209.     get: TEHandle  TEUpdate
  210. ;m
  211.     
  212.  
  213. :m SCROLL:        \ ( dx dy -- )
  214.     0 0  SetOrigin
  215.     get: TEHandle  TEScroll  ;m
  216.  
  217.  
  218. :m size: ( -- len )  \ returns the length of the text
  219.     ptr: TEHandle  size: teRecord ;m         \ note message to class
  220.  
  221. :m TextHandle:        \ ( -- hndl )
  222.     get: TEhandle  TEGetText  dup put: textHandle  ;m
  223.  
  224. :m textaddr:        \ ( -- addr )    \ addr of the first char of the TE text
  225.     textHandle: self  @  ;m
  226.  
  227. :m get:    ( -- $addr len )
  228.     textaddr: self
  229.     size: self  ;m
  230.  
  231. :m getText&lock:  ( -- hState addr len )
  232.     get: self                \ I'll do this first, before locking the handle, since
  233.                             \  I can't assume TE won't unlock it
  234.     getState: textHandle  down
  235.     lock: textHandle  ;m
  236.  
  237. :m >hState:  ( hState -- )
  238.     textHandle: self drop
  239.     setState: textHandle
  240. ;m
  241.  
  242. :m put: ( $addr len -- )
  243.     get: TEHandle  TESetText
  244.     update: self  ;m
  245.  
  246. :m insert:  ( addr len -- )
  247.     get: TEHandle  TEInsert
  248. ;m
  249.  
  250. :m activate:
  251.     noClip
  252.     get: TEHandle  TEActivate ;m
  253.  
  254. :m deactivate:
  255.     noClip
  256.     get: TEHandle  TEDeactivate ;m
  257.  
  258. :m release:
  259.     get: TEHandle  TEDispose
  260.     clear: TEHandle ;m
  261.  
  262. :m click:
  263.     where: fEvent  g->l
  264.     mods: fevent $ 200 and  0<> negate    \ extend if shift key (need a
  265.                                         \  Pascal-style boolean
  266.     handle: self  TEClick
  267.     ;m
  268.  
  269. :m select:  ( start end -- )  \ hilites the given range
  270.     get: TEHandle  TESetSelect ;m
  271.  
  272. :m selectAll:  \ hilites all of the text
  273.     0 ( start)
  274.     size: self  ( end)
  275.     select: self ;m
  276.  
  277. :m selStart:  ( -- n )
  278.     ptr: TEHandle selStart: teRecord ;m
  279.  
  280. :m selEnd:  ( -- n )
  281.     ptr: TEHandle selEnd: teRecord ;m
  282.  
  283. :m lastchar:  ( -- char )    \ return last character in TE
  284.     textaddr: self  size: self 1- + c@  ;m
  285.  
  286.  
  287. :m key:  { char \ bSel eSel -- }
  288.         \ TE for some reason doesn't handle forward delete, so we
  289.         \  have to special-case it.
  290.  
  291.     char 127 =
  292.     IF                            \ yes, it's forward delete
  293.         selStart: self -> bSel
  294.         selEnd: self   -> eSel
  295.         bSel eSel =
  296.         IF    eSel  size: self  >=  ?EXIT
  297.             eSel 1+ dup  select: self
  298.         ELSE
  299.             eSel  size: self <
  300.             IF  bSel eSel 1+  select: self  THEN
  301.         THEN
  302.         8  -> char
  303.     THEN
  304.     char  get: TEHandle  TEKey
  305. ;m
  306.  
  307.  
  308. 0 value kludge
  309.  
  310. :m #lines:    ( -- n )
  311.     0 -> kludge
  312.     ptr: TEHandle  #lines: class_as> teRecord
  313.     lastchar: self  ret = IF -1 -> kludge 1+ THEN    \ kludge Apple line numbering scheme!!
  314. ;m
  315.  
  316. \ given the zero-based line number, return the character# of the start of
  317. \ that line
  318.  
  319. :m at:  { n -- linestart }
  320.     n ( kludge + ) 1+  #lines: self >     \ abort" TE linestart index out of range"
  321.     IF  #lines: self  1- -> n  THEN
  322.     ptr: TEHandle  addrLineStart: class_as> teRecord
  323.     n 2* + w@
  324. \    dup textaddr: self + c@  ret =  IF 1+ THEN
  325. ;m
  326.  
  327.  
  328. \ In the initial System 8, there's a bug in TEGetPoint - it expects a
  329. \  spurious initial parameter!  So for now I've kludged xcalls to say
  330. \  it has 3 parms.
  331.  
  332. :m GETPOINT:  { offset -- x y }    \ given the char offset into the text, return the
  333.                                 \ corresponding x y location  See IM V-269.
  334. \ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  335. \ Apparently the call TEGetPoint has a bug in current PPC implementations
  336. \ - the 2 parms are required to be in r4 and r5, instead of r3 and r4!
  337. \ So we have to kludge this particular call to think it takes one more
  338. \ cell than it really does.  If Apple fixes the bug, we'll need to delete
  339. \ this line.  There's also 2 lines in zCallsMod.txt.
  340.  
  341. [ ppc? ] [if]  0  [then]
  342.     
  343. \ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  344.  
  345.     offset  get: TEHandle  TEGetPoint  unpack  ;m
  346.  
  347.  
  348. :m currentLine:     ( -- n )
  349.     selend: self  getpoint: self  ( x y ) nip          ( cursor.y )
  350.     ptr: TEHandle ( dest) gettopy: rect  -            ( cursor.y - dest.top )
  351.     
  352.     lineheight: self / 1-
  353.     
  354.     selend: self  size: self =     \ true if at last char
  355.     size: self  and    \ and if not an empty size
  356.     IF
  357.         lastchar: self  ret =
  358.         IF    \ uh-oh, handle special case where last char is a ret
  359.             1+
  360.         THEN
  361.     THEN
  362.     ;m
  363.  
  364.  
  365. :m getLineN:  { n -- addr len }
  366.     n at: self dup  -> lineStart  -> lineEnd
  367.         \ set lineStart and lineEnd to char offs of curr line start in case we EXIT
  368.  
  369.     textaddr: self  lineStart +          \ addr of line start
  370.  
  371.     #lines: self 1 - n =
  372.     IF                                    \ we are on the last line
  373.         lastchar: self
  374.         ret =
  375.             IF        \ we are on the last line AND just beyond a carriage return!
  376.                 0  EXIT                    \ return zero len and get out
  377.             THEN
  378.  
  379.         size: self
  380.         lineStart -  ( len )
  381.     
  382.     ELSE        
  383.         linestart drop
  384.         n 1 + at: self
  385.         lineStart - 1 -  ( len )
  386.     THEN
  387.     ( len )  dup lineStart +  -> lineEnd
  388. ;m
  389.  
  390. :m getLine:  { \ n -- addr len }    \ returns the line with the current selection.
  391.  
  392.     size: self 0= IF textaddr: self 0 EXIT    THEN    \ out if no text
  393.  
  394.     currentLine: self -> n
  395.     n getLineN: self
  396. ;m
  397.  
  398.  
  399. :m LINEEND: { \ len pos -- pos }    \ return the character position corresponding to the
  400.                                     \ end of the last line of the current selection.
  401.     selend: self size: self =
  402.     IF    \ we are at the end of the text
  403.         size: self
  404.     ELSE
  405.         currentline: self  at: self  ( linestart ) -> pos
  406.         getline: self nip -> len
  407.         pos len +
  408.     THEN ;m
  409.  
  410. :m getselect: ( -- addr len )    \ returns hilited selection
  411.     ptr: TEHandle    getselect: teRecord  ;m
  412.  
  413. :m getSelect&lock:  ( hState addr len -- )
  414.     getSelect: self            \ I'll do this first, before locking the handle, since
  415.                             \  I can't assume TE won't unlock it
  416.     textHandle: self drop
  417.     getState: textHandle  down
  418.     lock: textHandle
  419. ;m
  420.  
  421.  
  422. :m IDLE:    \ May94 mh - Setting cursor now moved to TEScroller
  423.     get: TEHandle  TEIdle    
  424.  ;m
  425.  
  426. :m DUMP:
  427.     selstart: self
  428.     selend: self
  429.     currentline: self
  430.     lineEnd: self
  431.     size: self  { ss se cl le sz -- }
  432. \    ss " selstart "        >debug
  433. \    se " selend "            >debug
  434. \    cl " currentline "     >debug
  435. \    le " lineEnd "         >debug
  436. \    sz " size "             >debug
  437. ;m
  438.  
  439. ;CLASS
  440.